package com.example.firstjavamqtt.service.log.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.firstjavamqtt.Constants.DeviceTypeConstants;
import com.example.firstjavamqtt.service.log.DeviceLogService;
import com.example.firstjavamqtt.service.base.DeviceService;
import com.example.firstjavamqtt.common.excepiton.GlobalException;
import com.example.firstjavamqtt.common.result.ResultCodeEnum;
import com.example.firstjavamqtt.factory.OperationFactory;
import com.example.firstjavamqtt.mapper.DeviceLogMapper;
import com.example.firstjavamqtt.model.base.Device;
import com.example.firstjavamqtt.model.dto.log.DeviceLogDto;
import com.example.firstjavamqtt.model.log.DeviceLog;
import com.example.firstjavamqtt.utils.BeanListUtils;
import com.example.firstjavamqtt.utils.LogRequestUtil;
import com.example.firstjavamqtt.utils.RedisUtil;
import com.example.firstjavamqtt.utils.SqlUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@Service
public class DeviceLogServiceImpl extends ServiceImpl<DeviceLogMapper, DeviceLog> implements DeviceLogService {

    private DeviceService deviceService;

    @Autowired
    RedisUtil redisUtil;

    //存储设备日志
    @Override
    public void saveDeviceLog(String string, HttpServletRequest request) {
        DeviceLog deviceLog = getBaseDeviceLog(string);
        LogRequestUtil.setRequest(deviceLog, request);
        baseMapper.insert(deviceLog);
    }

    //保存设备日志
    @Override
    public void saveDeviceLog(String string) {
        DeviceLog deviceLog = getBaseDeviceLog(string);
        baseMapper.insert(deviceLog);
    }

    //根据id删除某条日志
    @Override
    public void deleteDeviceLogById(int id) {
        int i = baseMapper.deleteById(id);
        if (i < 1) {
            throw new GlobalException(ResultCodeEnum.PARAM_ERROR);
        }
    }

    //删除某设备id下的所有日志
    @Override
    public void deleteDeviceLogByDeviceId(String deviceId) {
        int i = baseMapper.delete(getWrapperByDeviceId(deviceId));
        if (i < 1) {
            throw new GlobalException(ResultCodeEnum.PARAM_ERROR);
        }
    }

    //分页查询所有设备日志
    @Override
    public Page<DeviceLog> getAllDeviceLog(int pageNum, int limit) {
        Page<DeviceLog> page = new Page<>(pageNum, limit);
        return baseMapper.selectPage(page, null);
    }

    //根据设备类型查询所有设备日志
    @Override
    public Page<DeviceLog> getAllDeviceLogByDeviceType(String deviceType, int pageNum, int limit) {
        Page<DeviceLog> page = new Page<>(pageNum, limit);
        return baseMapper.selectPage(page, getWrapperByDeviceType(deviceType));
    }

    //根据设备ID查询所有设备日志
    @Override
    public Page<DeviceLog> getAllDeviceLogByDeviceId(String deviceId, int pageNum, int limit) {
        Page<DeviceLog> page = new Page<>(pageNum, limit);
        return baseMapper.selectPage(page, getWrapperByDeviceId(deviceId));
    }

    //根据ID查询设备日志
    @Override
    public DeviceLog getDeviceLogById(int id) {
        DeviceLog deviceLog = baseMapper.selectById(id);
        if (deviceLog == null) {
            throw new GlobalException(ResultCodeEnum.DATA_ERROR);
        }
        return deviceLog;
    }

    //获取设备日志(模糊查询)
    @Override
    public Page<DeviceLog> getDeviceLog(DeviceLogDto deviceLogDto, int pageNum, int limit) {
        Page<DeviceLog> page = new Page<>(pageNum, limit);
        QueryWrapper<DeviceLog> wrapper = new SqlUtil.Dynamic<DeviceLog>()
                .like("device_type", deviceLogDto.getDeviceType())
                .like("device_id", deviceLogDto.getDeviceId())
                .like("operation", deviceLogDto.getOperation())
                .ge("operation_date", deviceLogDto.getStartDate())
                .le("operation_date", deviceLogDto.getEndDate())
                .build();
        return baseMapper.selectPage(page, wrapper);
    }

    //根据设备ID保存红外设备日志
    @Override
    public void saveInfraredByDeviceId(String deviceId) {
        List<Object> objects = redisUtil.lGet("Infrared:" + deviceId, 0, -1);
        if (CollectionUtils.isEmpty(objects)) {
            return;
        }
        List<DeviceLog> deviceLogs = BeanListUtils.copyListProperties(objects, DeviceLog::new);
        for (DeviceLog deviceLog : deviceLogs) {
            deviceLog.setOperation("有人走过");
            deviceLog.setDeviceType(DeviceTypeConstants.INFRARED);
        }
        this.saveBatch(deviceLogs);
    }

    @Override
    public void deleteDeviceByDeviceType(String deviceType) {
        int i = baseMapper.delete(getWrapperByDeviceType(deviceType));
        if (i < 1) {
            throw new GlobalException(ResultCodeEnum.PARAM_ERROR);
        }
    }

    @Override
    public void deleteDeviceLogByBatchId(ArrayList<Integer> batchId) {
        int i = baseMapper.deleteBatchIds(batchId);
        if (i < 1) {
            throw new GlobalException(ResultCodeEnum.PARAM_ERROR);
        }
    }

    //根据设备ID获取wrapper
    private QueryWrapper<DeviceLog> getWrapperByDeviceId(String deviceId) {
        return new QueryWrapper<DeviceLog>().eq("device_id", deviceId);
    }

    //根据设备类型获取wrapper
    private QueryWrapper<DeviceLog> getWrapperByDeviceType(String deviceType) {
        return new QueryWrapper<DeviceLog>().eq("device_type", deviceType);
    }

    //获取要设置的设备的基本信息
    private DeviceLog getDeviceLog(Device device, String deviceType, String operation) {
        DeviceLog deviceLog = new DeviceLog();
        BeanUtils.copyProperties(device, deviceLog);
        deviceLog.setDeviceType(deviceType);
        deviceLog.setOperation(operation);
        return deviceLog;
    }

    private DeviceLog getBaseDeviceLog(String string) {
        Device device = JSONObject.parseObject(string, Device.class);
        if (!device.isOnline()) {
            throw new GlobalException(ResultCodeEnum.OFFLINE);
        }
        //根据设备id查询到设备类型
        String deviceType = deviceService.getDeviceByDeviceId(device.getDeviceId()).getDeviceType();
        //调用工厂获取设备操作
        String operation = OperationFactory.getOperation(string, deviceType);
        //设置设备log
        return getDeviceLog(device, deviceType, operation);
    }

    @Autowired
    public void setDeviceService(DeviceService deviceService) {
        this.deviceService = deviceService;
    }
}
